package primetest.impl.controler;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;

import org.primefaces.event.RowEditEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import primetest.dto.ChargeDto;
import primetest.dto.DepartmentDto;
import primetest.dto.DoctorDto;
import primetest.dto.MedicineDto;
import primetest.dto.PatientDto;
import primetest.dto.TreatmentRecordDto;
import primetest.dto.TreatmentRecordDto.Medicine;
import primetest.faces.TreatmentRecordListModel;
import primetest.impl.manager.SessionManager;
import primetest.impl.service.ChargeService;
import primetest.impl.service.DoctorService;
import primetest.impl.service.MedicineService;
import primetest.impl.service.TreatmentRecordService;

@Named("treatmentControler")
@SessionScoped
public class TreatmentControler implements Serializable {

	/**
	 *
	 */
	private static final long serialVersionUID = -7705555541485532754L;

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	@Inject
	private SessionManager sessionManager;
	@Inject
	private MedicineService medicineService;
	@Inject
	private ChargeService chargeService;


	private TreatmentRecordListModel treatmentRecordList = null;
	private List<TreatmentRecordDto> baseTreatmentRecordList;
	private TreatmentRecordDto selectedTreatmentRecord = new TreatmentRecordDto();
	private TreatmentRecordDto backTreatmentRecord = new TreatmentRecordDto();
	private TreatmentRecordDto newTreatmentRecord = new TreatmentRecordDto();
	private int treatmentRecordListFirst;
	private int patientListFirst;
	private boolean editMode = false;
	private boolean addMode = false;
	private List<TreatmentRecordDto> filteredTreatmentRecord;
	private List<PatientDto> filteredPatients;

	private DoctorDto doctor;
	private PatientDto currentPatient;
	private PatientDto selectedPatient;
	private MedicineDto selectedMedicine;
	private int medicineQuantity;
	private boolean addMedicineMode;

	public void startAddMedicine() {
		if (addMode) {
			for (Medicine m : newTreatmentRecord.getMedicines()) {
				if (m.key.getKey().equals(selectedMedicine.getKey())) {
					sessionManager.addGlobalMessageFatal(
							"Same Medicine Already exists", null);
					return;
				}
			}
			addMedicineMode = true;
		} else {
			for (Medicine m : selectedTreatmentRecord.getMedicines()) {
				if (m.key.getKey().equals(selectedMedicine.getKey())) {
					sessionManager.addGlobalMessageFatal(
							"Same Medicine Already exists", null);
					return;
				}
			}
			addMedicineMode = true;
		}
	}

	public void addMedicine() {
		if (medicineQuantity > selectedMedicine.getQuantity()) {
			sessionManager.addGlobalMessageFatal("Stock Quantity not enough",
					null);
			return;
		}
		if (addMode) {
			newTreatmentRecord.getMedicines().add(
					new Medicine(selectedMedicine, medicineQuantity));
		} else {
			selectedTreatmentRecord.getMedicines().add(
					new Medicine(selectedMedicine, medicineQuantity));
		}
		addMedicineMode = false;
	}

	public void cancelAddMedicine() {
		addMedicineMode = false;
	}

	public boolean getEditMode() {
		return editMode;
	}

	public boolean getAddMode() {
		return addMode;
	}

	public boolean getEditOrAddMode() {
		return editMode || addMode;
	}

	public String getHeader() {
		if (addMode) {
			return "Add";
		} else {
			return "Edit";
		}
	}


	@Inject
	private TreatmentRecordService treatmentRecordService;
//	@Inject
//	private PatientService patientService;
	@Inject
	private DoctorService doctorService;


	private List<DepartmentDto> departmentList = null;
	private List<DoctorDto> doctorList = null;
	private List<PatientDto> patientList = null;

	public TreatmentRecordListModel getTreatmentRecordList() {
		if (baseTreatmentRecordList == null) {
			try {
				if (selectedPatient != null) {
					baseTreatmentRecordList = treatmentRecordService
							.getTreatmentRecordList(selectedPatient.getSeq(),
									-1, -1, null, null, -1);
					treatmentRecordList = new TreatmentRecordListModel(
							baseTreatmentRecordList);
				}
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}

		return baseTreatmentRecordList == null ? new TreatmentRecordListModel(
				new ArrayList<TreatmentRecordDto>()) : treatmentRecordList;
	}

	public TreatmentRecordDto getSelectedTreatmentRecord() {
		return selectedTreatmentRecord;
	}

	public void setSelectedTreatmentRecord(
			TreatmentRecordDto selectedTreatmentRecord) {
		this.selectedTreatmentRecord = selectedTreatmentRecord;
	}

	public TreatmentRecordDto getTreatmentRecord() {
		if (editMode) {
			return selectedTreatmentRecord;
		} else {
			return newTreatmentRecord;
		}
	}

	public void setTreatmentRecord(
			TreatmentRecordDto treatmentRecord) {
		if (editMode) {
			this.selectedTreatmentRecord = treatmentRecord;
		} else {
			this.newTreatmentRecord = treatmentRecord;
		}
	}

	public int getTreatmentRecordListFirst() {
		return treatmentRecordListFirst;
	}

	public void setTreatmentRecordListFirst(int first) {
		this.treatmentRecordListFirst = first;
	}

	public TreatmentRecordDto getNewTreatmentRecord() {
		return newTreatmentRecord;
	}

	public void setNewTreatmentRecord(TreatmentRecordDto newTreatmentRecord) {
		this.newTreatmentRecord = newTreatmentRecord;
	}

	public void saveEditTreatmentRecord(boolean flag) {
		try {
			if (selectedTreatmentRecord.isValid()) {
				if (flag) {
					selectedTreatmentRecord.setStatus(TreatmentRecordDto.SAVE_STATUS);
					for (Medicine mSel : selectedTreatmentRecord.getMedicines()) {
						medicineService
									.modifyQuantity(mSel.key, -mSel.quantity);
					}

				}
				selectedTreatmentRecord.save();
				treatmentRecordService
						.updateTreatmentRecord(selectedTreatmentRecord);
				logger.debug("save the selectedTreatmentRecord" + " sympton: "
						+ selectedTreatmentRecord.getSymptom() + " seq: "
						+ selectedTreatmentRecord.getSeq());
				editMode = false;
				if (flag) {
					ChargeDto chargeDto = new ChargeDto(selectedTreatmentRecord);
					chargeService.addCharge(chargeDto);
				}
			} else {
				sessionManager.addGlobalMessageFatal("TreatDate invalid", null);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void startEditTreatmentRecord() {
		editMode = true;
		backTreatmentRecord.setAll(selectedTreatmentRecord);
	}

	public void cancelEditTreatmentRecord() {
		editMode = false;
		selectedTreatmentRecord.setAll(backTreatmentRecord);
	}

	public void startAddTreatmentRecord() {
		addMode = true;
		newTreatmentRecord = new TreatmentRecordDto();
		newTreatmentRecord.setDoctorDto(doctor);
		newTreatmentRecord.setPatientDto(selectedPatient);
	}

	public void startViewTreatmentRecord() {
		baseTreatmentRecordList = null;
	}

	public void addNewTreatmentRecord(boolean flag) throws IOException {
		if (newTreatmentRecord.isValid()) {
			if (flag) {
				newTreatmentRecord.setStatus(TreatmentRecordDto.SAVE_STATUS);
				for (Medicine mNew : newTreatmentRecord.getMedicines()) {
					medicineService.modifyQuantity(mNew.key, - mNew.quantity);
				}
			}
			newTreatmentRecord.save();
			treatmentRecordService.addTreatmentRecord(newTreatmentRecord);
			deletePatientFromQueue();
			addMode = false;
			baseTreatmentRecordList = null;
			sessionManager.addGlobalMessageInfo("Add Treatment Record success",
					null);
			if (flag) {
				ChargeDto chargeDto = new ChargeDto(newTreatmentRecord);
				chargeService.addCharge(chargeDto);
			}
		} else {
			sessionManager
					.addGlobalMessageFatal("Treatment Date invalid", null);
		}
	}

	public void cancelAddTreatmentRecord() {
		addMode = false;
	}

	public List<DepartmentDto> getDepartmentList() {
		return departmentList;
	}

	public void setDepartmentList(List<DepartmentDto> departmentList) {
		this.departmentList = departmentList;
	}

	public List<DoctorDto> getDoctorList() throws IOException {
		doctorList = doctorService.getDoctorList();
		return doctorList;
	}

	public List<PatientDto> getPatientList() throws IOException {
		if (patientList == null) {
			patientList = getDoctor().getPatientList();
		}
		return patientList;
	}

	public void deletePatient() {
		patientList.remove(selectedPatient);
	}

	private void deletePatientFromQueue() throws IOException {
		getDoctor().getPatientQueue().remove(selectedPatient);
	}

	public List<TreatmentRecordDto> getFilteredTreatmentRecord() {
		return filteredTreatmentRecord;
	}

	public void setFilteredTreatmentRecord(
			List<TreatmentRecordDto> filteredTreatmentRecord) {
		this.filteredTreatmentRecord = filteredTreatmentRecord;
	}

	public DoctorDto getDoctor() throws IOException {
		if (doctor == null) {
			doctor = sessionManager.getLoginUser();
		}
		return doctor;
	}

	public PatientDto getCurrentPatient() throws IOException {
		if (currentPatient == null) {
			currentPatient = getDoctor().getPatientQueue().peek();
		}
		return currentPatient;
	}

	public PatientDto getSelectedPatient() {
		return selectedPatient;
	}

	public void setSelectedPatient(PatientDto selectedPatient) {
		this.selectedPatient = selectedPatient;
	}

	public List<PatientDto> getFilteredPatients() {
		return filteredPatients;
	}

	public void setFilteredPatients(List<PatientDto> filteredPatients) {
		this.filteredPatients = filteredPatients;
	}

	public int getPatientListFirst() {
		return patientListFirst;
	}

	public void setPatientListFirst(int patientListFirst) {
		this.patientListFirst = patientListFirst;
	}

	public MedicineDto getSelectedMedicine() {
		return selectedMedicine;
	}

	public void setSelectedMedicine(MedicineDto selectedMedicine) {
		this.selectedMedicine = selectedMedicine;
	}

	public boolean isAddMedicineMode() {
		return addMedicineMode;
	}

	public void setAddMedicineMode(boolean addMedicineMode) {
		this.addMedicineMode = addMedicineMode;
	}

	public int getMedicineQuantity() {
		return medicineQuantity;
	}

	public void setMedicineQuantity(int medicineQuantity) {
		this.medicineQuantity = medicineQuantity;
	}

	public void saveTreatmentRecord(boolean flag) throws IOException {
		if (editMode) {
			saveEditTreatmentRecord(flag);
		} else {
			addNewTreatmentRecord(flag);
		}
	}

	public void cancelSaveTreatmentRecord() {
		if (editMode) {
			cancelEditTreatmentRecord();
		} else {
			cancelAddTreatmentRecord();
		}
	}

	public void onRowEdit(RowEditEvent event) {
//        FacesMessage msg = new FacesMessage("Car Edited", ((Car) event.getObject()).getId());
//        FacesContext.getCurrentInstance().addMessage(null, msg);
    }

    public void onRowCancel(RowEditEvent event) {
//        FacesMessage msg = new FacesMessage("Edit Cancelled", ((Car) event.getObject()).getId());
//        FacesContext.getCurrentInstance().addMessage(null, msg);
    }
}
